package com.enba.mallapi.module.area.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.enba.boot.core.base.Result;
import com.enba.boot.core.enums.YesOrNoEnum;
import com.enba.boot.core.utils.TreeNode;
import com.enba.boot.core.utils.TreeUtils;
import com.enba.boot.redis.RedisOperator;
import com.enba.mallapi.module.area.controller.resp.AreaInfoTreeNodeResp;
import com.enba.mallapi.module.area.entity.AreaInfo;
import com.enba.mallapi.module.area.service.IAreaInfoService;
import io.swagger.annotations.ApiOperation;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 区域信息表
 *
 * @author 恩爸编程
 * @since 2025-08-04
 */
@RestController
@RequestMapping("/api/area/areaInfo")
public class AreaInfoController {

  private final IAreaInfoService areaInfoService;

  private final RedisOperator redisOperator;

  // 区域信息树锁
  private static final String AREA_TREE_LOCK_KEY = "areaTree:lockKey";
  // 区域信息树数据
  private static final String AREA_TREE_DAT_KEY = "areaTree:dataKey";

  public AreaInfoController(IAreaInfoService areaInfoService, RedisOperator redisOperator) {
    this.areaInfoService = areaInfoService;
    this.redisOperator = redisOperator;
  }

  /** 获取所有区域信息树 */
  @ApiOperation(value = "获取所有区域信息树")
  @GetMapping("/all-tree")
  public Result<List<?>> getAreaTree() {
    // 先从redis中获取，如果没有则从数据库中获取
    List<AreaInfoTreeNodeResp> treeNodeList =
        redisOperator.get(AREA_TREE_DAT_KEY, new TypeReference<List<AreaInfoTreeNodeResp>>() {});
    if (CollectionUtil.isNotEmpty(treeNodeList)) {
      return Result.success(treeNodeList);
    } else {
      List<TreeNode> treeNodes =
          // 加锁
          redisOperator.executeWithLockNoBlock(
              AREA_TREE_LOCK_KEY,
              30L,
              () -> {
                // 获取所有区域信息 组装成树结构
                List<TreeNode> treeNodeList_ =
                    TreeUtils.buildTree(
                        () ->
                            areaInfoService
                                .getBaseMapper()
                                .selectList(
                                    Wrappers.<AreaInfo>lambdaQuery()
                                        .eq(AreaInfo::getDeleted, YesOrNoEnum.NO.getCode())),
                        menuList ->
                            menuList.stream()
                                .map(
                                    e -> {
                                      AreaInfoTreeNodeResp areaInfoTreeNodeResp =
                                          new AreaInfoTreeNodeResp(
                                              e.getCode(), e.getParentCode(), e.getName());
                                      areaInfoTreeNodeResp.setLevel(e.getLevel());

                                      return areaInfoTreeNodeResp;
                                    })
                                .collect(Collectors.toList()));

                //  设置缓存
                redisOperator.set(AREA_TREE_DAT_KEY, treeNodeList_, 60 * 60 * 24 * 7);
                return treeNodeList_;
              });

      return Result.success(treeNodes);
    }
  }
}
